package com.zengqingfa.sharding.jdbc.demo.sharding.range;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Range;
import com.zengqingfa.sharding.jdbc.demo.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;

/**
 *
 * @fileName: ShardingDatabaseRangeAlgorithm
 * @author: zengqf3
 * @date: 2021-3-28 21:40
 * @description: 分库算法
 */
@Slf4j
public class ShardingDatabaseRangeAlgorithm implements RangeShardingAlgorithm<Timestamp> {

    /**
     * 范围分片算法
     *
     * @param availableTargetNames 所有配置的库列表
     * @param rangeShardingValue   分片值,范围分片算法必须提供开始时间和结束时间
     * @return 所匹配库的结果
     */
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames,
            RangeShardingValue<Timestamp> rangeShardingValue) {
        log.info("availableTargetNames={}", JSON.toJSONString(availableTargetNames));
        log.info("rangeShardingValue={}", JSON.toJSONString(rangeShardingValue));
        final ArrayList<String> result = new ArrayList<>();
        Range<Timestamp> range = rangeShardingValue.getValueRange();
        long startMillisecond = range.lowerEndpoint().getTime();
        long endMillisecond = range.upperEndpoint().getTime();

        // 起始年和结束年
        int startYear = Integer.parseInt(DateUtil.getYear(startMillisecond));
        int endYear = Integer.parseInt(DateUtil.getYear(endMillisecond));

        return startYear == endYear ?
                theSameYear(String.valueOf(startYear), availableTargetNames, result) :
                differentYear(startYear, endYear, availableTargetNames, result);
    }

    /**
     * 同一年，说明只需要一个库
     * @param startTime
     * @param availableTargetNames
     * @param result
     * @return
     */
    private Collection<String> theSameYear(String startTime, Collection<String> availableTargetNames,
            ArrayList<String> result) {
        for (String availableTargetName : availableTargetNames) {
            if (availableTargetName.endsWith(startTime)) {
                log.info("availableTargetName={}",availableTargetName);
                result.add(availableTargetName);
            }
        }
        return result;
    }


    /**
     * 跨年
     * @param startYear
     * @param endYear
     * @param availableTargetNames
     * @param result
     * @return
     */
    private Collection<String> differentYear(int startYear, int endYear, Collection<String> availableTargetNames,
            ArrayList<String> result) {
        for (String availableTargetName : availableTargetNames) {
            for (int i = startYear; i <= endYear; i++) {
                if (availableTargetName.endsWith(String.valueOf(i))) {
                    log.info("availableTargetName={}",availableTargetName);
                    result.add(availableTargetName);
                }
            }
        }
        return result;
    }
}
